package com.wstuo.common.jbpm;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipInputStream;

import javax.imageio.ImageIO;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.jbpm.api.Execution;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.HistoryService;
import org.jbpm.api.IdentityService;
import org.jbpm.api.ManagementService;
import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessDefinitionQuery;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.ProcessInstanceQuery;
import org.jbpm.api.RepositoryService;
import org.jbpm.api.TaskQuery;
import org.jbpm.api.TaskService;
import org.jbpm.api.history.HistoryActivityInstance;
import org.jbpm.api.history.HistoryProcessInstance;
import org.jbpm.api.history.HistoryProcessInstanceQuery;
import org.jbpm.api.history.HistoryTask;
import org.jbpm.api.history.HistoryTaskQuery;
import org.jbpm.api.identity.Group;
import org.jbpm.api.identity.User;
import org.jbpm.api.model.Activity;
import org.jbpm.api.model.ActivityCoordinates;
import org.jbpm.api.model.Transition;
import org.jbpm.api.task.Participation;
import org.jbpm.api.task.Task;
import org.jbpm.pvm.internal.history.model.HistoryTaskInstanceImpl;
import org.jbpm.pvm.internal.model.ActivityImpl;
import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.wstuo.common.security.dao.IUserDAO;
import com.wstuo.common.bpm.dao.IFlowActivityDAO;
import com.wstuo.common.bpm.dto.ActivityCoordinatesDTO;
import com.wstuo.common.bpm.dto.FlowActivityDTO;
import com.wstuo.common.bpm.dto.FlowPropertyDTO;
import com.wstuo.common.bpm.dto.FlowTaskDTO;
import com.wstuo.common.bpm.dto.FlowTransitionDTO;
import com.wstuo.common.bpm.dto.HistoryTaskDTO;
import com.wstuo.common.bpm.dto.ParticipationDTO;
import com.wstuo.common.bpm.dto.ProcessDefinitionDTO;
import com.wstuo.common.bpm.dto.ProcessDetailDTO;
import com.wstuo.common.bpm.dto.ProcessHistoriesDTO;
import com.wstuo.common.bpm.dto.ProcessHistoriesQueryDTO;
import com.wstuo.common.bpm.dto.ProcessInstanceDTO;
import com.wstuo.common.bpm.dto.TaskDTO;
import com.wstuo.common.bpm.entity.FlowActivity;
import com.wstuo.common.dto.PageDTO;
import com.wstuo.common.exception.ApplicationException;
import com.wstuo.common.jbpm.comparator.ComparatorOutcome;
import com.wstuo.common.jbpm.dao.IJbpmHistoryTaskInstanceDAO;
import com.wstuo.common.jbpm.jpdlModel.JpdlModel;
import com.wstuo.common.jbpm.jpdlModel.JpdlModelDrawer;

/**
 * The facade class for JBPM
 * 
 * @author wstuo
 */
public class JbpmFacade implements IJbpmFacade {
	@Autowired
	private IUserDAO userDAO;
	@Autowired
	protected ProcessEngine processEngine;
	@Autowired
	private IFlowActivityDAO flowActivityDAO;
	@Autowired
	private IJbpmHistoryTaskInstanceDAO jbpmHistoryTaskInstanceDAO;
	protected RepositoryService repositoryService;
	protected ExecutionService executionService;
	protected ManagementService managementService;
	protected TaskService taskService;
	protected HistoryService historyService;
	protected IdentityService identityService;
	private static final Logger LOGGER = Logger.getLogger(JbpmFacade.class);
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#setProcessEngine(org.jbpm.api.ProcessEngine)
	 */
	public void setProcessEngine(ProcessEngine pe) {
		this.processEngine = pe;
		init();
	}

	/**
	 * 初始所有服务对象 initialize all service object refer to the process engine
	 */
	protected void init() {
		repositoryService = processEngine.getRepositoryService();
		executionService = processEngine.getExecutionService();
		historyService = processEngine.getHistoryService();
		managementService = processEngine.getManagementService();
		taskService = processEngine.getTaskService();
		identityService = processEngine.getIdentityService();
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#deployJpdl(java.io.File)
	 */
	@Transactional
	public String deployJpdl(File file) {
		String deploymentId = null;

		try {
			deploymentId = deployJpdl(new FileInputStream(file));
		} catch (FileNotFoundException e) {
			LOGGER.error("JbpmFacade deployJpdl", e);
			throw new RuntimeException(e);
		}
		return deploymentId;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#deployJpdl(java.io.InputStream)
	 */
	@Transactional
	public String deployJpdl(InputStream fis) {
		String deploymentId = repositoryService.createDeployment().addResourcesFromZipInputStream(new ZipInputStream(fis)).deploy();

		return deploymentId;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findProcessDefinitionIdByDeploymentId(java.lang.String)
	 */
	public String findProcessDefinitionIdByDeploymentId(String deploymentId) {
		ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).uniqueResult();
		if (pd != null) {
			return pd.getId();
		} else {
			return null;
		}
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#undeployJpdl(java.lang.String)
	 */
	public void undeployJpdl(String deploymentId) {
		repositoryService.deleteDeploymentCascade(deploymentId);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#undeployJpdlById(java.lang.String)
	 */
	public void undeployJpdlById(String pid) {
		ProcessDefinition pd = this.getDefinitionById(pid);
		if (pd != null) {
			repositoryService.deleteDeploymentCascade(pd.getDeploymentId());
		}
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findLatestProcessDefinitions()
	 */
	public List<ProcessDefinition> findLatestProcessDefinitions() {
		// retrieve all process definitions
		List<ProcessDefinition> processDefinitions = findAllProcessDefinitions();
		Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>();

		for (ProcessDefinition pd : processDefinitions) {
			String key = pd.getKey();
			ProcessDefinition definition = map.get(key);

			if ((definition == null) || (definition.getVersion() < pd.getVersion())) {
				map.put(key, pd);
			}
		}

		return new ArrayList(map.values());
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findLatestProcessDefinitions(com.wstuo.common.bpm.dto.ProcessDefinitionDTO, int, int, java.lang.String, java.lang.String)
	 */
	public PageDTO findLatestProcessDefinitions(ProcessDefinitionDTO qdto, int start, int limit, String sord, String sidx) {
		ProcessDefinitionQuery pdQuery = repositoryService.createProcessDefinitionQuery();
		if (qdto != null) {
			if (StringUtils.hasText(qdto.getDeploymentId()))
				pdQuery.deploymentId(qdto.getDeploymentId());
			if (StringUtils.hasText(qdto.getKey()))
				pdQuery.processDefinitionKey(qdto.getKey());
			if (StringUtils.hasText(qdto.getName()))
				pdQuery.processDefinitionName(qdto.getName());
			if (StringUtils.hasText(qdto.getId()))
				pdQuery.processDefinitionId(qdto.getId());
		}
		int totalSize = (int) pdQuery.count();
		String sidxs = ProcessDefinitionQuery.PROPERTY_ID;
		if ("name".equals(sidx)) {
			sidxs = ProcessDefinitionQuery.PROPERTY_NAME;
		}
		if ("deploymentId".equals(sidx)) {
			sidxs = ProcessDefinitionQuery.PROPERTY_DEPLOYMENT_TIMESTAMP;
		}
		if ("id".equals(sidx)) {
			sidxs = ProcessDefinitionQuery.PROPERTY_ID;
		}
		if ("key".equals(sidx)) {
			sidxs = ProcessDefinitionQuery.PROPERTY_KEY;
		}
		if ("version".equals(sidx)) {
			sidxs = ProcessDefinitionQuery.PROPERTY_VERSION;
		}
		if ("desc".equals(sord)) {
			pdQuery = pdQuery.orderDesc(sidxs);
		} else {
			pdQuery = pdQuery.orderAsc(sidxs);
		}
		pdQuery = pdQuery.page(start, limit);
		List<ProcessDefinition> processDefinitions = pdQuery.list();

		// Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>( );
		List<ProcessDefinitionDTO> dtos = new ArrayList<ProcessDefinitionDTO>(processDefinitions.size());

		for (ProcessDefinition pd : processDefinitions) {
			ProcessDefinitionDTO pdto = processDefinition2Dto(pd);
			// String key = pd.getKey( );
			// ProcessDefinition definition = map.get( key );
			// if ( ( definition == null ) || ( definition.getVersion( ) < pd.getVersion( ) ) )
			// {
			// map.put( key, pd );
			// }
			dtos.add(pdto);
		}

		PageDTO page = new PageDTO();
		page.setTotalSize(totalSize);
		page.setData(dtos);

		return page;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#processDefinition2Dto(org.jbpm.api.ProcessDefinition)
	 */
	public ProcessDefinitionDTO processDefinition2Dto(ProcessDefinition entity) {
		ProcessDefinitionDTO dto = new ProcessDefinitionDTO();
		dto.setId(entity.getId());
		dto.setKey(entity.getKey());
		dto.setName(entity.getName());
		dto.setDescription(entity.getDescription());
		dto.setVersion(entity.getVersion());
		dto.setDeploymentId(entity.getDeploymentId());
		dto.setImageResourceName(entity.getImageResourceName());

		return dto;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getProcessImageByDeploymentId(java.lang.String)
	 */
	public InputStream getProcessImageByDeploymentId(String processDeploymentId) {
		ProcessDefinition processDefinition = getProcessDefinitionByDeploymentId(processDeploymentId);
		return repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getImageResourceName());
	}
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getProcessImage(java.lang.String)
	 */
	public InputStream getProcessImage(String processId) {
		ProcessDefinition processDefinition = getDefinitionById(processId);
		return repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getImageResourceName());
	}
	public String getProcessXml(String processId) {
		ProcessDefinition processDefinition = getDefinitionById(processId);
		Set<String> names = repositoryService.getResourceNames(processDefinition.getDeploymentId());
		String xml="";
		for (String n :names) {
			if (n.indexOf(".jpdl.xml") != -1) {
			    InputStream in = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), n);
		        try {
		        	BufferedReader reader = new BufferedReader(new InputStreamReader(in,"UTF-8")); // 实例化输入流，并获取网页代码
			        String s; // 依次循环，至到读的值为空
			        StringBuilder sb = new StringBuilder();
					while ((s = reader.readLine()) != null) {
						sb.append(s);
					}
					reader.close();
					xml = sb.toString();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return xml;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findInstancesByProcessId(java.lang.String)
	 */
	public List<ProcessInstance> findInstancesByProcessId(String pid) {
		ProcessInstanceQuery query = executionService.createProcessInstanceQuery();

		if (StringUtils.hasText(pid)) {
			query.processDefinitionId(pid);
		}
		return query.list();
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findInstances(java.lang.String, int, int)
	 */
	public PageDTO findInstances(String processDefinitionId, int start, int limit) {
		ProcessInstanceQuery query = executionService.createProcessInstanceQuery();
		if (StringUtils.hasText(processDefinitionId)) {
			query.processDefinitionId(processDefinitionId);
		}
		int totalSize = (int) query.count();
		List<ProcessInstance> data = query.page(start, limit).list();
		PageDTO p = new PageDTO();
		p.setTotalSize(totalSize);

		List<ProcessInstanceDTO> dtos = new ArrayList<ProcessInstanceDTO>(data.size());

		for (ProcessInstance entity : data) {

			ProcessInstanceDTO adto = processInstance2Dto(entity);
			dtos.add(adto);
		}
		p.setData(dtos);

		return p;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#processInstance2Dto(org.jbpm.api.ProcessInstance)
	 */
	public ProcessInstanceDTO processInstance2Dto(ProcessInstance entity) {
		ProcessInstanceDTO dto = new ProcessInstanceDTO();
		dto.setId(entity.getId());
		dto.setKey(entity.getKey());
		dto.setPriority(entity.getPriority());
		dto.setProcessDefinitionId(entity.getProcessDefinitionId());
		dto.setState(entity.getState());
		return dto;
	}
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getInstanceById(java.lang.String)
	 */
	public ProcessInstance getInstanceById(String instanceId) {

		return executionService.findProcessInstanceById(instanceId);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#startProcessByKey(java.lang.String, java.util.Map)
	 */
	public ProcessInstance startProcessByKey(String processKey, Map<String, Object> variables) {
		ProcessInstance pi = executionService.startProcessInstanceByKey(processKey, variables);
		return pi;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#startProcessAndNext(java.lang.String, java.util.Map)
	 */
	public String startProcessAndNext(String key, Map<String, Object> variables) {
		ProcessInstance pi = startProcessByKey(key, variables);

		pi = signalNextExecution(pi);

		return pi.getId();
	}
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#startProcessByDefinitionId(java.lang.String, java.util.Map)
	 */
	public ProcessInstance startProcessByDefinitionId(String processDefinitionId, Map<String, Object> variables) {
		ProcessInstance pi = executionService.startProcessInstanceById(processDefinitionId, variables);
		return pi;
	}
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#startProcessAndNext(java.lang.String, java.lang.String, java.util.Map)
	 */
	public String startProcessAndNext(String processType, String value, Map<String, Object> variables) {
		ProcessInstance pi = null;
		if ("ProcessDefinitionId".equals(processType))
			pi = startProcessByDefinitionId(value, variables);
		else
			pi = startProcessByKey(value, variables);
		pi = signalNextExecution(pi);
		return pi.getId();
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#signalNextExecution(org.jbpm.api.ProcessInstance)
	 */
	public ProcessInstance signalNextExecution(ProcessInstance pi) {
		String nextActivityName = getActivityNamesByInstance(pi).iterator().next();
		Execution nextExecution = pi.findActiveExecutionIn(nextActivityName);
		pi = executionService.signalExecutionById(nextExecution.getId());
		return pi;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#endProcessInstance(java.lang.String)
	 */
	public void endProcessInstance(String pid) {
		executionService.endProcessInstance(pid, "end");
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getActivityNamesByInstance(org.jbpm.api.ProcessInstance)
	 */
	public Set<String> getActivityNamesByInstance(ProcessInstance processInstance) {
		return processInstance.findActiveActivityNames();
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getActivityCoordinatesByInstance(org.jbpm.api.ProcessInstance)
	 */
	public ActivityCoordinates getActivityCoordinatesByInstance(ProcessInstance processInstance) {
		ActivityCoordinates ac = repositoryService.getActivityCoordinates(processInstance.getProcessDefinitionId(), processInstance.findActiveActivityNames().iterator().next());
		return ac;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getHistoryActivityCoordinatesByInstance(java.lang.String)
	 */
	public List<ActivityCoordinatesDTO> getHistoryActivityCoordinatesByInstance(String processId) {
		List<ActivityCoordinatesDTO> activityCoordinatesDTOs = new ArrayList<ActivityCoordinatesDTO>();
		ProcessInstance pi = getInstanceById(processId);
		HistoryProcessInstance hpi = historyService.createHistoryProcessInstanceQuery().processInstanceId(processId).uniqueResult();
		ActivityCoordinates ac2 = null;
		if (pi != null) {
			ac2 = getActivityCoordinatesByInstance(pi);
		}
		List<HistoryActivityInstance> hisIns = historyService.createHistoryActivityInstanceQuery().processInstanceId(processId).list();
		for (Iterator<HistoryActivityInstance> iter = hisIns.iterator(); iter.hasNext();) {
			String activityName = iter.next().getActivityName();
			ActivityCoordinates ac = null;
			if (pi != null) {
				ac = repositoryService.getActivityCoordinates(pi.getProcessDefinitionId(), activityName);
			}
			if (ac2 != null && ac != null && !ac2.equals(ac)) {
				ActivityCoordinatesDTO dto = new ActivityCoordinatesDTO();
				ActivityCoordinatesDTO.entity2dto(ac, dto);
				activityCoordinatesDTOs.add(dto);
			}
			if (ac2 == null) {
				ac = repositoryService.getActivityCoordinates(hpi.getProcessDefinitionId(), activityName);
				ActivityCoordinatesDTO dto = new ActivityCoordinatesDTO();
				ActivityCoordinatesDTO.entity2dto(ac, dto);
				activityCoordinatesDTOs.add(dto);
			}
		}
		return activityCoordinatesDTOs;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findHistories()
	 */
	public List<HistoryProcessInstance> findHistories() {
		List<HistoryProcessInstance> histories = historyService.createHistoryProcessInstanceQuery().list();
		return histories;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findPageHistories(com.wstuo.common.bpm.dto.ProcessHistoriesQueryDTO, int, int)
	 */
	public PageDTO findPageHistories(ProcessHistoriesQueryDTO dto, int start, int limit) {
		HistoryProcessInstanceQuery query = historyService.createHistoryProcessInstanceQuery();
		if (dto != null) {
			if (StringUtils.hasText(dto.getKey())) {
				query.processInstanceKey(dto.getKey());
			}
			if (StringUtils.hasText(dto.getProcessDefinitionId())) {
				query.processDefinitionId(dto.getProcessDefinitionId());
			}
			if (StringUtils.hasText(dto.getProcessInstanceId())) {
				query.processInstanceId(dto.getProcessInstanceId());
			}
			if (StringUtils.hasText(dto.getState())) {
				query.state(dto.getState());
			}
		}

		PageDTO p = new PageDTO();
		int totalSize = (int) query.count();
		p.setTotalSize(totalSize);

		query.orderDesc("startTime");
		List<HistoryProcessInstance> data = query.page(start, limit).list();
		List<ProcessHistoriesDTO> dtos = new ArrayList<ProcessHistoriesDTO>(data.size());

		for (HistoryProcessInstance entity : data) {
			ProcessHistoriesDTO adto = processHistories2Dto(entity);
			dtos.add(adto);
		}

		p.setData(dtos);

		return p;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findHistoryProcessInstanceByPid(java.lang.String)
	 */
	public ProcessHistoriesDTO findHistoryProcessInstanceByPid(String pid) {
		HistoryProcessInstance hpi = historyService.createHistoryProcessInstanceQuery().processInstanceId(pid).uniqueResult();
		ProcessHistoriesDTO phd = processHistories2Dto(hpi);
		return phd;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#processHistories2Dto(org.jbpm.api.history.HistoryProcessInstance)
	 */
	public ProcessHistoriesDTO processHistories2Dto(HistoryProcessInstance entity) {
		ProcessHistoriesDTO dto = new ProcessHistoriesDTO();
		dto.setKey(entity.getKey());
		dto.setDuration(entity.getDuration());
		dto.setEndActivityName(entity.getEndActivityName());
		dto.setEndTime(entity.getEndTime());
		dto.setProcessDefinitionId(entity.getProcessDefinitionId());
		dto.setProcessInstanceId(entity.getProcessInstanceId());
		dto.setStartTime(entity.getStartTime());
		dto.setState(entity.getState());
		return dto;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findTasks(java.lang.String)
	 */
	public List<Task> findTasks(String username) {
		List<Task> groupTasks = taskService.findGroupTasks(username);
		List<Task> personTasks = taskService.findPersonalTasks(username);
		List<Task> assigneeTasks = taskService.createTaskQuery().assignee(username).list();
		List<Task> tasks = (List<Task>) CollectionUtils.union(groupTasks, personTasks);
		tasks = (List<Task>) CollectionUtils.union(tasks, assigneeTasks);

		return tasks;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#task2Dto(org.jbpm.api.task.Task)
	 */
	public TaskDTO task2Dto(Task task) {
		TaskDTO taskDto = new TaskDTO();
		taskDto.setActivityName(task.getActivityName());
		taskDto.setAssignee(task.getAssignee());
		taskDto.setCreateTime(task.getCreateTime());
		taskDto.setDescription(task.getDescription());
		taskDto.setDuedate(task.getDuedate());
		taskDto.setExecutionId(task.getExecutionId());
		taskDto.setFormResourceName(task.getFormResourceName());
		taskDto.setId(task.getId());
		taskDto.setName(task.getName());
		taskDto.setPriority(task.getPriority());
		taskDto.setProgress(task.getProgress());

		Map<String, Object> variables = this.getVariablesByTaskId(task.getId());

		taskDto.setVariables(variables);

		return taskDto;
	}
	public static void dto2entity(Object dto, Object entity) {
		try {
			if (dto != null) {
				BeanUtils.copyProperties(entity, dto);
			}
		} catch (Exception ex) {
			throw new ApplicationException(ex);
		}
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findTaskDtos(java.lang.String)
	 */
	public List<TaskDTO> findTaskDtos(String username) {
		List<Task> tasks = findTasks(username);
		List<TaskDTO> taskDtos = new ArrayList<TaskDTO>();
		if ((tasks != null) && (tasks.size() > 0)) {
			for (Task task : tasks) {
				taskDtos.add(task2Dto(task));
			}
		}
		return taskDtos;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findTaskDtos(java.lang.String, int, int)
	 */
	public PageDTO findTaskDtos(String username, int start, int limit) {
		TaskQuery query = taskService.createTaskQuery().assignee(username);
		query.orderDesc("createTime");
		int totalSize = (int) query.count();
		List<Task> data = query.page(start, limit).list();
		PageDTO p = new PageDTO();
		p.setTotalSize(totalSize);

		List<TaskDTO> dtos = new ArrayList<TaskDTO>(data.size());

		for (Task entity : data) {
			TaskDTO dto = task2Dto(entity);
			dtos.add(dto);
		}

		p.setData(dtos);

		return p;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findGroupTaskDtos(java.lang.String, int, int)
	 */
	public PageDTO findGroupTaskDtos(String username, int start, int limit) {
		List<Task> query = taskService.findGroupTasks(username);
		int totalSize = (int) query.size();
		List<Task> data = new ArrayList<Task>();
		data = query;
		Collections.reverse(data);
		PageDTO p = new PageDTO();
		p.setTotalSize(totalSize);

		List<TaskDTO> dtos = new ArrayList<TaskDTO>(data.size());

		for (Task entity : data) {
			TaskDTO dto = task2Dto(entity);
			dtos.add(dto);
		}

		p.setData(dtos);

		return p;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findGroupTasks(java.lang.String)
	 */
	public List<Task> findGroupTasks(String userId) {
		return taskService.findGroupTasks(userId);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findPersonalTasks(java.lang.String, int, int)
	 */
	public PageDTO findPersonalTasks(String userId, int start, int limit) {
		PageDTO pageDTO = new PageDTO();
		TaskQuery tq = taskService.createTaskQuery();
		tq.assignee(userId);
		int totalSize = (int) tq.count();
		tq.orderDesc("createTime");
		tq.page(start, limit);

		List<Task> tasks = tq.list();
		List<TaskDTO> taskDtos = new ArrayList<TaskDTO>();

		for (Task entity : tasks) {
			TaskDTO dto = task2Dto(entity);
			taskDtos.add(dto);
		}
		pageDTO.setTotalSize(totalSize);
		pageDTO.setData(taskDtos);
		return pageDTO;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#countPersonalTasks(java.lang.String)
	 */
	public int countPersonalTasks(String userId) {
		TaskQuery tq = taskService.createTaskQuery();
		tq.assignee(userId);
		int totalSize = (int) tq.count();
		return totalSize;
	}
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#takeTask(java.lang.String, java.lang.String, java.lang.String)
	 */
	public void takeTask(String taskId, String username, String to) {
		Task task = taskService.getTask(taskId);
		taskService.completeTask(task.getId(), to);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#takeTask(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	public void takeTask(String pid, String activityName, String username, String to) {
		String taskId = getTaskId(pid, activityName);
		Task task = taskService.getTask(taskId);
		taskService.completeTask(task.getId(), to);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#taskTask(java.lang.String, java.lang.String)
	 */
	public void taskTask(String taskId, String username) {
		taskService.takeTask(taskId, username);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#assignTask(java.lang.String, java.lang.String)
	 */
	public void assignTask(String taskId, String username) {
		taskService.assignTask(taskId, username);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#addTaskParticipatingGroup(java.lang.String, java.lang.String, java.lang.String)
	 */
	public void addTaskParticipatingGroup(String taskId, String groupId, String participationType) {
		taskService.addTaskParticipatingGroup(taskId, groupId, participationType);
	}
	
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#addTaskParticipatingGroup(java.lang.String, java.lang.String, java.lang.String)
	 */
	public void addTaskParticipatingUser(String taskId, String userId, String participationType) {
		taskService.addTaskParticipatingUser(taskId, userId, participationType);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getTaskId(java.lang.String, java.lang.String)
	 */
	public String getTaskId(String pid, String activityName) {
		String result = null;
		List<Task> tasks = taskService.createTaskQuery().processInstanceId(pid).activityName(activityName).list();

		if (tasks.size() >= 1) {
			result = tasks.get(tasks.size() - 1).getId();
		} else {
			Task task = taskService.createTaskQuery().processInstanceId(pid).activityName(activityName).uniqueResult();
			if (task != null) {
				result = task.getId();
			}
		}
		return result;
	}
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findTaskByPidActivityName(java.lang.String, java.lang.String)
	 */
	public List<Task> findTaskByPidActivityName(String pid, String activityName) {
		List<Task> tasks = taskService.createTaskQuery().processInstanceId(pid).activityName(activityName).list();
		return tasks;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getCurrentPiMyTask(java.lang.String, java.lang.String)
	 */
	public List<TaskDTO> getCurrentPiMyTask(String processInstanceId, String userName) {
		String nextActivityName = getActivityNamesByInstance(getInstanceById(processInstanceId)).iterator().next();
		List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).activityName(nextActivityName).assignee(userName).list();
		List<TaskDTO> dtos = null;
		if (tasks != null && tasks.size() > 0) {
			dtos = new ArrayList<TaskDTO>(tasks.size());
			for (Task entity : tasks) {
				TaskDTO dto = task2Dto(entity);
				dtos.add(dto);
			}
		}
		return dtos;
	}
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findCurrentTaskByPid(java.lang.String)
	 */
	public List<TaskDTO> findCurrentTaskByPid(String pid) {
		String nextActivityName = getActivityNamesByInstance(getInstanceById(pid)).iterator().next();
		List<Task> tasks = taskService.createTaskQuery().processInstanceId(pid).activityName(nextActivityName).list();
		List<TaskDTO> dtos = new ArrayList<TaskDTO>(tasks.size());

		for (Task entity : tasks) {
			TaskDTO dto = task2Dto(entity);
			dtos.add(dto);
		}

		return dtos;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getActivityNameByPid(java.lang.String)
	 */
	public String getActivityNameByPid(String pid) {
		ProcessInstance pi = getInstanceById(pid);
		String activityName = null;
		if (pi != null) {
			activityName = getActivityNamesByInstance(pi).iterator().next();
		}
		return activityName;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#assignActivity(java.lang.String, java.lang.String, java.lang.String)
	 */
	public void assignActivity(String pid, String activityName, String username) {
		Task task = taskService.createTaskQuery().processInstanceId(pid).activityName(activityName).uniqueResult();
		taskService.assignTask(task.getId(), username);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getVariableByTaskId(java.lang.String, java.lang.String)
	 */
	public Object getVariableByTaskId(String taskId, String variableName) {
		Object obj = null;
		try {
			obj = taskService.getVariable(taskId, variableName);
		} catch (Exception ex) {
			LOGGER.error("JbpmFacade getVariableByTaskId", ex);
		}
		return obj;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getVariablesByTaskId(java.lang.String)
	 */
	public Map<String, Object> getVariablesByTaskId(String taskId) {
		Set<String> variableNames = taskService.getVariableNames(taskId);

		return taskService.getVariables(taskId, variableNames);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getVariablesByExecutionId(java.lang.String, java.lang.String)
	 */
	public Map<String, Object> getVariablesByExecutionId(String taskId, String executionId) throws Exception {
		Set<String> variableNames = taskService.getVariableNames(taskId);
		Map<String, Object> variables = executionService.getVariables(executionId, variableNames);

		return variables;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getTask(java.lang.String)
	 */
	public Task getTask(String taskId) {
		return taskService.getTask(taskId);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findUsers()
	 */
	public List<User> findUsers() {
		return identityService.findUsers();
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#createGroup(java.lang.String, java.lang.String)
	 */
	@Transactional()
	public void createGroup(String groupName, String parentGroupId) {
		if (StringUtils.hasText(parentGroupId)) {
			Group parentGroup = identityService.findGroupById(parentGroupId);
			if (parentGroup == null) {
				identityService.createGroup(parentGroupId);
			}
		}
		if (StringUtils.hasText(groupName)) {
			Group group = identityService.findGroupById(groupName);
			if (group == null) {
				identityService.createGroup(groupName, null, parentGroupId);
			}
		}
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#createUser(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	public void createUser(String id, String familyName, String givenName, String businessEmail) {
		User user = identityService.findUserById(id);
		if (user == null)
			identityService.createUser(id, familyName, givenName, businessEmail);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#modifyUser(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	public void modifyUser(String id, String familyName, String givenName, String businessEmail) {
		if (null != identityService.findUserById(id)) {
			identityService.deleteUser(id);
		}
		createUser(id, familyName, givenName, businessEmail);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#createMembership(java.lang.String, java.lang.String, java.lang.String[])
	 */
	@Transactional()
	public void createMembership(String groupId, String parentGroupId, String[] userIds) {
		Group g = identityService.findGroupById(groupId);

		if (g == null) {
			Group parentGroup = identityService.findGroupById(parentGroupId);
			if (parentGroup != null) {
				identityService.createGroup(groupId, null, parentGroupId);
			} else {
				identityService.createGroup(groupId);
			}
		}

		for (String userId : userIds) {
			boolean exist = false;
			// 判断是否已经在当前组下,如果在此组下则不需要再添加关联
			List<String> groups = identityService.findGroupIdsByUser(userId);
			for (String str : groups) {
				if (groupId.equals(str)) {
					exist = true;
					break;
				}
			}

			if (!exist)
				identityService.createMembership(userId, groupId);

		}
	}

	/**
	 * 查询全部流程实例
	 * 
	 * @return List<ProcessDefinition>
	 */
	protected List<ProcessDefinition> findAllProcessDefinitions() {
		List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().orderAsc(ProcessDefinitionQuery.PROPERTY_NAME).list();

		return processDefinitions;
	}

	/**
	 * 根据流程定义ID获取流程定义
	 * 
	 * @param processId
	 * @return process definition
	 */
	protected ProcessDefinition getDefinitionById(String processId) {
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processId).uniqueResult();
		return processDefinition;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getProcessDefinitionByDeploymentId(java.lang.String)
	 */
	public ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId) {
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).uniqueResult();
		return processDefinition;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getOutcomes(java.lang.String)
	 */
	public Set<String> getOutcomes(String processInstanceId) {
		Set<String> outcomesSet = new HashSet<String>();
		if (processInstanceId != null) {
			ProcessInstance pi = getInstanceById(processInstanceId);
			if (pi != null) {
				String nextActivityName = getActivityNamesByInstance(pi).iterator().next();

				String taskId = getTaskId(processInstanceId, nextActivityName);
				if (taskId != null) {
					Task task = taskService.getTask(taskId);
					Set<String> outcomme = taskService.getOutcomes(task.getId());
					for (String omme : outcomme) {
						outcomesSet.add(omme);
					}
				}

			}
		}
		return outcomesSet;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findOutcomesByTaskId(java.lang.String)
	 */
	public Set<String> findOutcomesByTaskId(String taskId) {
		return taskService.getOutcomes(taskId);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getTaskByPid(java.lang.String)
	 */
	public Task getTaskByPid(String pid) {
		ProcessInstance pi = this.getInstanceById(pid);
		String nextActivityName = this.getActivityNamesByInstance(pi).iterator().next();
		return taskService.createTaskQuery().processInstanceId(pid).activityName(nextActivityName).uniqueResult();
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#completeTask(java.lang.String, java.lang.String, java.util.Map)
	 */
	public void completeTask(String taskId, String next, Map<String, Object> variables) {
		taskService.completeTask(taskId, next, variables);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#completeTask(java.lang.String, java.lang.String, java.lang.String, java.util.Map)
	 */
	public void completeTask(String userId, String taskId, String next, Map<String, Object> variables) {
		Task task = taskService.getTask(taskId);
		if (task.getAssignee() == null)
			taskService.takeTask(taskId, userId);
		taskService.completeTask(taskId, next, variables);
	}
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#completeTask(java.lang.String, java.util.Map)
	 */
	public void completeTask(String taskId, Map<String, Object> variables) {
		taskService.completeTask(taskId, variables);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#completeTask(java.lang.String, java.lang.String)
	 */
	public void completeTask(String taskId, String next) {
		taskService.completeTask(taskId, next);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#completeTask(java.lang.String, java.lang.String, java.lang.String)
	 */
	public void completeTask(String userId, String taskId, String next) {
		Task task = taskService.getTask(taskId);
		if (task!=null && task.getAssignee() == null)
			taskService.takeTask(taskId, userId);
		taskService.completeTask(taskId, next);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#completeTask(java.lang.String)
	 */
	public void completeTask(String taskId) {
		taskService.completeTask(taskId);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findHistoryTask(java.lang.String, java.lang.String, int, int)
	 */
	public PageDTO findHistoryTask(String pid, String assignee, int start, int limit) {
		PageDTO pageDto = new PageDTO();
		List<HistoryTask> list = new ArrayList<HistoryTask>();
		HistoryTaskQuery htq = processEngine.getHistoryService().createHistoryTaskQuery();
		if (StringUtils.hasText(pid)) 
			htq.executionId(pid);

		if (StringUtils.hasText(assignee))
			htq.assignee(assignee).state("completed");
		int totalSize = (int) htq.count();

		htq.orderDesc("createTime");

		pageDto.setTotalSize(totalSize);

		list = htq.page(start, limit).list();

		List<HistoryTaskDTO> hts = new ArrayList<HistoryTaskDTO>();
		if (list != null && list.size() > 0) {
			for (HistoryTask ht : list) {
				HistoryTaskDTO htdto = new HistoryTaskDTO();
				HistoryTaskDTO.entity2dto(ht, htdto);
				HistoryTaskInstanceImpl hti = jbpmHistoryTaskInstanceDAO.getHistoryTaskInstanceByTaskId(ht.getId()); 
				htdto.setActivityName(hti.getActivityName());
				com.wstuo.common.security.entity.User user =  userDAO.findUniqueBy("loginName", ht.getAssignee());
				if (user != null) {
					htdto.setAssignee(user.getFullName());
				}
				hts.add(htdto);
			}
		}
		pageDto.setData(hts);
		pageDto.setTotalSize(totalSize);

		return pageDto;
	}
	
	
	public String findAssigneeByHistoryTask(ProcessInstance pi,String activityName) {
		
		String pid = pi.getId();
		List<HistoryTask> list = new ArrayList<HistoryTask>(); 
		HistoryTaskQuery htq = processEngine.getHistoryService().createHistoryTaskQuery();
		if (StringUtils.hasText(pid))
			htq.executionId(pid);
		
		htq.orderDesc("createTime");
		list = htq.list();
		
		String assignee = "";
		if (list != null && list.size() > 0) {
			for (HistoryTask ht : list) {
				HistoryTaskInstanceImpl hti = jbpmHistoryTaskInstanceDAO.getHistoryTaskInstanceByTaskId(ht.getId()); 
				if(ht.getOutcome()!=null && activityName.equals(hti.getActivityName())){
					assignee = ht.getAssignee();
					break;
				}
			}
		}
		return assignee;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findLastCompleteHistoryActivityInstance(java.lang.String)
	 */
	public HistoryTaskDTO findLastCompleteHistoryActivityInstance(String processInstanceId) {
		List<HistoryActivityInstance> hais = historyService.createHistoryActivityInstanceQuery().processInstanceId(processInstanceId).list();
		//System.out.println(hais.size()+"--size-");
		for (HistoryActivityInstance hai : hais) {
			/*System.out.println(hai.getStartTime());
			System.out.println(hai.getExecutionId()+"--ExecutionId");
			System.out.println(hai.getActivityName()+"--ActivityName--");
			System.out.println(hai.getTransitionNames()+"--TransitionNames--");
			for (String str : hai.getTransitionNames()) {
				System.out.println(str+"--TransitionName--");
			}
			System.out.println(hai.getDuration()+"--Duration--");*/
			
		}

		return null;

	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#countGetPendingTasks(java.lang.String)
	 */
	public Integer countGetPendingTasks(String assignee) {
		return 0;
	}
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#countMyProcessedTask(java.lang.String)
	 */
	public Integer countMyProcessedTask(String assignee) {
		HistoryTaskQuery htq = processEngine.getHistoryService().createHistoryTaskQuery();
		htq.assignee(assignee).state("completed");
		return (int) htq.count();
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#deployJpdlXml(java.io.File)
	 */
	@Transactional
	public String deployJpdlXml(File jpdlfile) {

		InputStream is;
		try {
			is = new FileInputStream(jpdlfile);
			try {
				JpdlModel jpdlModel = new JpdlModel(is);
				// 生成图片
				ImageIO.write(new JpdlModelDrawer().draw(jpdlModel), "png", new File(FlowDesigner.PROCESS_FILE_PATH + "/jpdl.png"));
			} catch (Exception e) {
				LOGGER.error("JbpmFacade deployJpdlXml Exception", e);
			}
		} catch (FileNotFoundException e1) {
			LOGGER.error("JbpmFacade deployJpdlXml FileNotFoundException", e1);
		}

		String deploymentId = null;
		try {
			File pngFile = new File(FlowDesigner.PROCESS_FILE_PATH + "/jpdl.png");
			deploymentId = repositoryService.createDeployment().addResourceFromInputStream("temp.jpdl.xml", new FileInputStream(jpdlfile)).addResourceFromInputStream("temp.png", new FileInputStream(pngFile)).deploy();
		} catch (FileNotFoundException e) {
			LOGGER.error("JbpmFacade deployJpdlXml FileNotFoundException", e);
		}
		return deploymentId;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findProcessDefinitionActivity(java.lang.String)
	 */
	@Transactional
	public FlowPropertyDTO findProcessDefinitionActivity(String processDefinitionId) {
		FlowPropertyDTO flowPropertyDTO = new FlowPropertyDTO();

		ProcessDefinition processDefinition = null;
		processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).uniqueResult();

		if(processDefinition==null){
			processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(processDefinitionId).uniqueResult();
		}
		
		if (processDefinition != null) {
			flowPropertyDTO.setProcessDefinitionId(processDefinition.getId());
			flowPropertyDTO.setDeploymentId(processDefinition.getDeploymentId());
		}

		ProcessDefinitionImpl definitionimpl = (ProcessDefinitionImpl) processDefinition;
		List<? extends Activity> list =new ArrayList<Activity>();
		if(definitionimpl!=null){
			list = definitionimpl.getActivities();
		}
		List<FlowActivityDTO> flowActivityDtos = new ArrayList<FlowActivityDTO>();
		for (Activity activity : list) {
			FlowActivityDTO flowActivityDTO = new FlowActivityDTO();
			flowActivityDTO.setActivityName(activity.getName());
			flowActivityDTO.setActivityType(activity.getType());

			List<? extends Transition> list1 = activity.getOutgoingTransitions();
			List<FlowTransitionDTO> flowTransitionDtos = new ArrayList<FlowTransitionDTO>();
			for (Transition t : list1) {
				FlowTransitionDTO flowTransitionDTO = new FlowTransitionDTO();
				flowTransitionDTO.setTransitionName(t.getName());
				flowTransitionDTO.setDestination(t.getDestination().getName());
				flowTransitionDtos.add(flowTransitionDTO);
			}
			flowActivityDTO.setFlowTransitionDto(flowTransitionDtos);
			flowActivityDtos.add(flowActivityDTO);
		}
		flowPropertyDTO.setFlowActivityDTO(flowActivityDtos);
		return flowPropertyDTO;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#findProcessDetail(java.lang.String)
	 */
	public List<ProcessDetailDTO> findProcessDetail(String pid) {

		List<ProcessDetailDTO> pdDTO = new ArrayList<ProcessDetailDTO>();
		// 出口
		if (StringUtils.hasText(pid)) {
			ProcessInstance pi = getInstanceById(pid);
			if (pi != null) {

				// 活动
				Set<String> activity = pi.findActiveActivityNames();
				for (String at : activity) {
					ProcessDetailDTO processDetailDTO = new ProcessDetailDTO();
					processDetailDTO.setActivityName(at);

					List<FlowTaskDTO> flowTaskDTOs = new ArrayList<FlowTaskDTO>();
					// 任务
					List<Task> tasks = taskService.createTaskQuery().processInstanceId(pid).activityName(at).list();
					for (Task task : tasks) {
						FlowTaskDTO flowTaskDTO = new FlowTaskDTO();
						List<ParticipationDTO> partsDTO = new ArrayList<ParticipationDTO>();
						List<Participation> parts = taskService.getTaskParticipations(task.getId());
						for (Participation p : parts) {
							ParticipationDTO dto = new ParticipationDTO();
							ParticipationDTO.entity2dto(p, dto);
							partsDTO.add(dto);
						}

						flowTaskDTO.setParticipationDTO(partsDTO);

						flowTaskDTO.setTaskId(task.getId());
						flowTaskDTO.setTaskName(task.getName());
						flowTaskDTO.setAssignee(task.getAssignee());
						flowTaskDTO.setDuedate(task.getDuedate());
						flowTaskDTO.setDescription(task.getDescription());
						flowTaskDTO.setPriority(task.getPriority());
						flowTaskDTO.setProgress(task.getProgress());
						flowTaskDTO.setFormResourceName(task.getFormResourceName());
						Set<String> outcomes = taskService.getOutcomes(task.getId());
						List<String> ocs = new ArrayList<String>(outcomes);
						ComparatorOutcome co = new ComparatorOutcome();
						Collections.sort(ocs, co);
						flowTaskDTO.setOutcomes(ocs);

						// 任务下的属性
						FlowActivity fa = flowActivityDAO.findFlowActivityByDeploymentId(pi.getProcessDefinitionId(), new String[]{"task"}, at);
						if (fa != null) {
							FlowActivityDTO faDTO = new FlowActivityDTO();
							FlowActivityDTO.entity2dto(fa, faDTO);
							if (fa.getTaskAction() != null) {
								String[] taskActions = fa.getTaskAction().split(",");
								Set<String> tas = new HashSet<String>();
								for (String str : taskActions) {
									tas.add(str);
								}
								faDTO.setTaskActions(tas);
							}
							flowTaskDTO.setFlowActivityDTO(faDTO);
						}
						flowTaskDTOs.add(flowTaskDTO);
					}
					processDetailDTO.setFlowTaskDTO(flowTaskDTOs);

					pdDTO.add(processDetailDTO);
				}

			}
		}
		return pdDTO;
	}
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getNextActivity(java.lang.String, java.lang.String, java.lang.String)
	 */
	public String getNextActivity(String pid, String taskName, String outcome) {
		String result = null;
		ProcessInstance pi = executionService.findProcessInstanceById(pid);
		ProcessDefinitionImpl processDefinition = (ProcessDefinitionImpl) repositoryService.createProcessDefinitionQuery().processDefinitionId(pi.getProcessDefinitionId()).uniqueResult();
		List list = processDefinition.getActivities();
		for (int i = 0; i < list.size(); i++) {
			ActivityImpl activityImpl = (ActivityImpl) list.get(i);
			String type = activityImpl.getType();

			if (taskName.equals(activityImpl.getName())) {// 判断活动名称是否是我要查的
				// 得到当前活动的所有出口
				List list1 = activityImpl.getOutgoingTransitions();
				for (Iterator iterator = list1.iterator(); iterator.hasNext();) {
					Transition ts = (Transition) iterator.next();
					if (outcome.equals(ts.getName())) {// 判断出口与过段名称一致
						if ("task".equals(type)) {
							result = ts.getDestination().getName();
						} else if ("foreach".equals(type)) {
							result = activityImpl.getName();
						}

					}

				}
			}
		}
		return result;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getNextActivityType(java.lang.String, java.lang.String, java.lang.String)
	 */
	public String getNextActivityType(String pid, String activityName, String outcome) {
		ProcessInstance pi = executionService.findProcessInstanceById(pid);
		ProcessDefinitionImpl processDefinition = (ProcessDefinitionImpl) repositoryService.createProcessDefinitionQuery().processDefinitionId(pi.getProcessDefinitionId()).uniqueResult();
		List list = processDefinition.getActivities();
		for (int i = 0; i < list.size(); i++) {
			ActivityImpl activityImpl = (ActivityImpl) list.get(i);
			if (activityName.equals(activityImpl.getName())) {// 当前活动名
				// 得到当前活动的所有出口
				List list1 = activityImpl.getOutgoingTransitions();
				for (Iterator iterator = list1.iterator(); iterator.hasNext();) {
					Transition ts = (Transition) iterator.next();
					if (outcome.equals(ts.getName())) {// 出口
						return ts.getDestination().getType();
					}

				}
			}
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#setInstanceVariable(java.lang.String, java.lang.String, java.lang.Object)
	 */
	public void setInstanceVariable(String pid, String name, Object value) {
		executionService.setVariable(pid, name, value);
		//executionService.createVariable(pid, name, value, true);
	}
	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#setInstanceVariables(java.lang.String, java.util.Map)
	 */
	public void setInstanceVariables(String pid, Map<String, Object> map) {
		executionService.setVariables(pid, map);
		//executionService.createVariables(pid, map, true);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getInstanceVariables(java.lang.String, java.lang.String)
	 */
	public Object getInstanceVariables(String pid, String variableName) {
		return executionService.getVariable(pid, variableName);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getInstanceVariableNames(java.lang.String)
	 */
	public Set<String> getInstanceVariableNames(String pid) {
		return executionService.getVariableNames(pid);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getInstanceVariables(java.lang.String, java.util.Set)
	 */
	public Map<String, Object> getInstanceVariables(String pid, Set<String> variableNames) {
		return executionService.getVariables(pid, variableNames);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#setTaskVariables(java.lang.String, java.util.Map)
	 */
	public void setTaskVariables(String taskId, Map<String, Object> variables) {
		taskService.setVariables(taskId, variables);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getTaskVariable(java.lang.String, java.lang.String)
	 */
	public Object getTaskVariable(String taskId, String variableName) {
		return taskService.getVariable(taskId, variableName);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getTaskVariableNames(java.lang.String)
	 */
	public Set<String> getTaskVariableNames(String taskId) {

		return taskService.getVariableNames(taskId);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#getTaskVariables(java.lang.String, java.util.Set)
	 */
	public Map<String, Object> getTaskVariables(String taskId, Set<String> variableNames) {
		return taskService.getVariables(taskId, variableNames);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#isEnded(java.lang.String)
	 */
	public boolean isEnded(String pid) {
		boolean result = true;
		ProcessInstance pi = executionService.findProcessInstanceById(pid);
		if (pi != null) {
			result = pi.isEnded();
		}
		return result;
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#deleteProcessInstance(java.lang.String)
	 */
	public void deleteProcessInstance(String pid) {
		executionService.deleteProcessInstance(pid);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#deleteProcessInstanceCascade(java.lang.String)
	 */
	public void deleteProcessInstanceCascade(String pid) {
		executionService.deleteProcessInstanceCascade(pid);
	}

	/* (non-Javadoc)
	 * @see com.wstuo.common.jbpm.IJbpmFacade#deleteTask(java.lang.String)
	 */
	public void deleteTask(String taskId) {
		taskService.deleteTask(taskId);
	}

}
